// OpenGLView.h : interface of the COpenGLView class
//
/////////////////////////////////////////////////////////////////////////////

#if !defined(AFX_OPENGLVIEW_H__5857316D_EA60_11D5_9FD5_00D0B718E2CD__INCLUDED_)
#define AFX_OPENGLVIEW_H__5857316D_EA60_11D5_9FD5_00D0B718E2CD__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <vector>
using std::vector;
#include <map>
using std::map;
#include <math.h>

#include "gl\gl.h"    // Include the standard OpenGL  headers
#include "gl\glu.h"   // Add the utility library
#include "gl\glaux.h" // Add in the auxiliary library (optional)

#include "vr.h"

#include "LightsDlg.h"

class COpenGLView : public CView
{
private:
	struct MyNormal {
		MyNormal () :x(0), y(0), z(0) {};
		float x,y,z;
		void normalize () {
			float size = sqrt(x*x + y*y + z*z);
			x /= size;
			y /= size;
			z /= size;
		}
	};
	struct MyColor {
		MyColor () :r(0), g(0), b(0) {};
		float r,g,b;
	};
	struct MyPoint {
		MyPoint () :x(0), y(0), z(0) {};
		float x,y,z;
	};
	struct MyVector {
		MyVector (float x_=0, float y_=0, float z_=0) :x(x_), y(y_), z(z_) {};
		MyVector cross (const MyVector &other) {
			MyVector &curr(*this);
			return MyVector(curr.y * other.z - curr.z * other.y, 
							curr.z * other.x - curr.x * other.z,
							curr.x * other.y - curr.y * other.x);
		}
		float x,y,z;
	};

protected: // create from serialization only
	COpenGLView();
	DECLARE_DYNCREATE(COpenGLView)

// Attributes
public:
	COpenGLDoc* GetDocument();

// Operations
public:
	void scale(int nValue);
	void rotate(int nValue);
	void translate(int nValue);
	void CalcCenterOfMass (void);
	void SetLights (void);
	void DoResizingBeforeTransformation();
	void DrawFog();
	void SetView();
private:
	LightsDlg m_lightsDlg;

	int m_nAxis;					// Axis of Action, X Y or Z
	int m_nAction;					// Rotate, Translate, Scale
	int m_nView;					// Orthographics, perspective
	bool m_bIsPerspective;			// is the view perspective
	bool m_bIsObjectSpace;
	bool m_bDrawBoundingBox;
	bool m_bDrawFaceNormals;
	bool m_bDrawVertexNormals;
	int m_nXCoord;
	int m_nYCoord;
	double m_dbMouseSensetivity;
	MyPoint m_CenterOfMass;
	bool m_bSaveToFile;
	bool m_bBackgroundImage;
	CString m_strBackImage;

	int m_fogMode;
	MyColor m_fogColor;
	float m_fogDensity;
	int m_fogStart, m_fogEnd;
	bool m_fogEnable;
	
	bool m_bUseFog;
	// Which fog filter To Use
	GLuint m_FogFilter;	

	bool m_bAntiAliasing;
	
	bool m_bBackFaceCulling;		// is Back Face Culling enabled

	CString m_strVrmlFileName;		// file name of VRML data

	int m_nLightShading;			// shading: Flat, Gouraud.
	int m_nViewMode;					// view mode: wireframe, full.

	double m_lMaterialAmbient;		// The Ambient in the scene
	double m_lMaterialDiffuse;		// The Diffuse in the scene
	double m_lMaterialSpecular;		// The Specular in the scene
	int m_nMaterialCosineFactor;	// The cosine factor for the specular

	int m_nArrLightDirection[3];	// holds the light direction


// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(COpenGLView)
	public:
	virtual void OnDraw(CDC* pDC);  // overridden to draw this view
	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
	protected:
	//}}AFX_VIRTUAL

// Implementation
public:
	virtual ~COpenGLView();
#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

protected:
	// shall init all matrices etc.
	void InitAll (void);
	void FreeData (void);

	BOOL InitializeOpenGL();
	BOOL SetupPixelFormat(PIXELFORMATDESCRIPTOR* pPFD = 0); // the '= 0' was added.
	BOOL SetupViewingFrustum(void);
	BOOL SetupViewingOrtho(void);
	BOOL SetupViewingOrthoConstAspect(void);

	virtual void RenderScene();
	void RenderIFS (VRIndexedFaceSet* ifs);

	HGLRC    m_hRC;			// holds the Rendering Context
	CDC*     m_pDC;			// holds the Device Context
	int m_WindowWidth;			// hold the windows width
	int m_WindowHeight;			// hold the windows height
	double m_AspectRatio;		// hold the fixed Aspect Ration

	VRNode *m_root;
	VRShape **m_transformedShapes;
	VRDWORD m_numShapes;

	// face colors:
	map<VRIndexedFaceSet*, vector<MyColor> > m_faceColors;
	vector<MyColor> &GetFaceColors (VRIndexedFaceSet* ifs);

	// vertex colors:
	map<VRIndexedFaceSet*, vector<MyColor> > m_vertexColors;
	vector<MyColor> &GetVertexColors (VRIndexedFaceSet* ifs);

	// face normals:
	map<VRIndexedFaceSet*, vector<MyNormal> > m_faceNormals;
	vector<MyNormal> &GetFaceNormals (VRIndexedFaceSet* ifs);
	void CalcFaceNormals (VRIndexedFaceSet* ifs, vector<MyNormal> &normals);

	// vertex normals:
	map<VRIndexedFaceSet*, vector<MyNormal> > m_vertexNormals;
	vector<MyNormal> &GetVertexNormals (VRIndexedFaceSet* ifs);
	void CalcVertexNormals(VRIndexedFaceSet* ifs, vector<MyNormal> &normals);

	unsigned CalcTotalFaces (VRIndexedFaceSet* ifs);

	// bounding box:
	MyPoint m_minCoord, m_maxCoord;
	void CalcBoundingBox (void);
	void DrawBoundingBox (void);

	void DrawFaceNormals (VRIndexedFaceSet* ifs);
	void DrawVertexNormals (VRIndexedFaceSet* ifs);

private:
	void draw_axis();


// Generated message map functions
protected:
	//{{AFX_MSG(COpenGLView)
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	afx_msg void OnDestroy();
	afx_msg void OnSize(UINT nType, int cx, int cy);
	afx_msg void OnFileLoad();
	afx_msg void OnViewOrthographic();
	afx_msg void OnUpdateViewOrthographic(CCmdUI* pCmdUI);
	afx_msg void OnViewPerspective();
	afx_msg void OnUpdateViewPerspective(CCmdUI* pCmdUI);
	afx_msg void OnActionRotate();
	afx_msg void OnUpdateActionRotate(CCmdUI* pCmdUI);
	afx_msg void OnActionScale();
	afx_msg void OnUpdateActionScale(CCmdUI* pCmdUI);
	afx_msg void OnActionTranslate();
	afx_msg void OnUpdateActionTranslate(CCmdUI* pCmdUI);
	afx_msg void OnAxisX();
	afx_msg void OnUpdateAxisX(CCmdUI* pCmdUI);
	afx_msg void OnAxisY();
	afx_msg void OnUpdateAxisY(CCmdUI* pCmdUI);
	afx_msg void OnAxisZ();
	afx_msg void OnUpdateAxisZ(CCmdUI* pCmdUI);
	afx_msg void OnOptionsBackfaceculling();
	afx_msg void OnUpdateOptionsBackfaceculling(CCmdUI* pCmdUI);
	afx_msg void OnLightShadingFlat();
	afx_msg void OnUpdateLightShadingFlat(CCmdUI* pCmdUI);
	afx_msg void OnLightShadingGouraud();
	afx_msg void OnUpdateLightShadingGouraud(CCmdUI* pCmdUI);
	afx_msg void OnLightConstants();
	afx_msg void OnLightDirection();
	afx_msg void OnButtonSubdivide();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnModeWireframe();
	afx_msg void OnUpdateModeWireframe(CCmdUI *pCmdUI);
	afx_msg void OnModeFull();
	afx_msg void OnUpdateModeFull(CCmdUI *pCmdUI);
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnSpaceObject();
	afx_msg void OnUpdateSpaceObject(CCmdUI *pCmdUI);
	afx_msg void OnSpaceWorld();
	afx_msg void OnUpdateSpaceWorld(CCmdUI *pCmdUI);
	afx_msg void OnNormalsFace();
	afx_msg void OnNormalsVertex();
	afx_msg void OnUpdateNormalsFace(CCmdUI *pCmdUI);
	afx_msg void OnUpdateNormalsVertex(CCmdUI *pCmdUI);
	afx_msg void OnOptionsBoundingbox();
	afx_msg void OnUpdateOptionsBoundingbox(CCmdUI *pCmdUI);
	afx_msg void OnOptionsAnti();
	afx_msg void OnUpdateOptionsAnti(CCmdUI *pCmdUI);
public:
	afx_msg void OnOptionsBackgroundimage();
public:
	afx_msg void OnUpdateOptionsBackgroundimage(CCmdUI *pCmdUI);
public:
	afx_msg void OnFileSave();
	afx_msg void OnOptionsMousesensitivity();
	afx_msg void OnLightFogsetting();
};

#ifndef _DEBUG  // debug version in OpenGLView.cpp
inline COpenGLDoc* COpenGLView::GetDocument()
   { return (COpenGLDoc*)m_pDocument; }
#endif

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_OPENGLVIEW_H__5857316D_EA60_11D5_9FD5_00D0B718E2CD__INCLUDED_)
